﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Analytics.BusinessLogic.Measures;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.DataObjects.Measures;
using DiscoveryLogic.Analytics.DataObjects.Networks;
using DiscoveryLogic.Common.Utilities;

namespace DiscoveryLogic.Analytics.Modules.Networks
{
    public class Connector
    {
        private Guid _ConnectorID;
        /// <summary></summary>
        public Guid ConnectorID
        {
            get
            {
                return this._ConnectorID;
            }
            set
            {
                this._ConnectorID = value;
            }
        }

        private Guid _FromID;
        /// <summary></summary>
        public Guid FromID
        {
            get
            {
                return this._FromID;
            }
            set
            {
                this._FromID = value;
            }
        }

        private Guid _ToID;
        /// <summary></summary>
        public Guid ToID
        {
            get
            {
                return this._ToID;
            }
            set
            {
                this._ToID = value;
            }
        }

        public Connector(Guid id, Guid fromID, Guid toID)
        {
            this._ConnectorID = id;
            this._FromID = fromID;
            this._ToID = toID;
        }
    }

    /// <summary>
    /// Interaction logic for NetworkStats.xaml
    /// </summary>
    public partial class NetworkStats : UserControl
    {
        private NetworkStatsPresenter _Presenter;

        public NetworkStats()
        {
            InitializeComponent();
        }

        public NetworkStats(NetworkStatsPresenter presenter)
            :this()
        {
            this._Presenter = presenter;
            this._Presenter.View = this;
        }


        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {

        }

        public void PopulateNetworkStats(Network network)
        {
            try
            {
                List<VerticeMeasure> vMeasures = VerticeMeasureManager.GetVerticeMeasures(network.NetworkName);
                this.dgStats.ItemsSource = vMeasures;
                if(vMeasures.Count>0)
                    this.exVertices.Visibility = Visibility.Visible;
                else
                    this.exVertices.Visibility = Visibility.Collapsed;

                NetworkMeasureWorker netMeasureWorker = new NetworkMeasureWorker(network);
                NetworkMeasure netMeasure = netMeasureWorker.GetNetworkMeasure();
                this.exGraph.Visibility = Visibility.Visible;
                this.txtDensity.Text = Math.Round(netMeasure.Density, 2).ToString();
                Dictionary<EntityType, Dictionary<string, EntityBase>> entities = network.GetEntities();
                this.panelEntityCount.Children.Clear();
                foreach(EntityType et in entities.Keys)
                {
                    Label lbl=new Label();
                    lbl.Content = string.Format("{0}: {1}", et.ToString(), entities[et].Count);
                    lbl.Margin=new Thickness(5,0,0,0);
                    this.panelEntityCount.Children.Add(lbl);
                }
                this.panelDistances.Children.Clear();
                Label lblEdgeDistance=new Label();
                lblEdgeDistance.Content = string.Format("Edge diameter: {0}", Math.Round(netMeasure.EdgeDiameter, 2));
                lblEdgeDistance.Margin=new Thickness(5,0,0,0);
                this.panelDistances.Children.Add(lblEdgeDistance);
                Label lblNodeDistance=new Label();
                lblNodeDistance.Content = string.Format("Node diameter: {0}", netMeasure.NodeDiameter);
                lblNodeDistance.Margin=new Thickness(5,0,0,0);
                this.panelDistances.Children.Add(lblNodeDistance);

                DataTable dtWalks = netMeasure.ToWalkTable();
                if(dtWalks.Rows.Count>500)
                {
                    DataTable dtCopy = dtWalks.Clone();
                    for(int i=0;i<500;i++)
                    {
                        dtCopy.Rows.Add(dtWalks.Rows[i].ItemArray);
                    }
                    dtWalks = dtCopy;
                }
                this.dgRoutes.ItemsSource = dtWalks.DefaultView;

                DataTable dtCluster = this.GetNetworkClustersAsTable(network);
                this.dgCliques.ItemsSource = dtCluster.DefaultView;
                DataTable dtClusterEntities = this.GetNetworkClusterEntitiesAsTable(network.NetworkName);
                this.dgCliqueEntities.ItemsSource = dtClusterEntities.DefaultView;
            }
            catch(Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
                MessageBox.Show(ex.Message);
            }
        }

        #region cluster 
        public DataTable GetNetworkClustersAsTable(Network network)
        {
            DataTable dtClusters = new DataTable();
            dtClusters.Columns.Add("ClusterID", typeof(int));
            dtClusters.Columns.Add("Density", typeof(double));
            dtClusters.Columns.Add("ClusterDegree", typeof(int));
            dtClusters.Columns.Add("EntityCount", typeof(int));
            dtClusters.Columns.Add("Coefficient", typeof (double));
            Dictionary<int, NetworkCluster> clusters = NetworkCluster.Read(network.NetworkName);
            NetworkMeasureWorker worker = new NetworkMeasureWorker(network);
            NetworkMeasure netMeasure = worker.GetNetworkMeasure();
            if(netMeasure.CommunityMeasures !=null && netMeasure.CommunityMeasures.Count>0)
            {
                foreach (CommunityMeasure measure in netMeasure.CommunityMeasures)
                {
                    DataRow dr = dtClusters.NewRow();
                    dr["ClusterID"] = measure.CommunityID;
                    dr["Density"] = measure.Density;
                    dr["ClusterDegree"] = measure.Degree;
                    dr["EntityCount"] = 0;
                    if(clusters.ContainsKey(measure.CommunityID))
                        dr["EntityCount"] = clusters[measure.CommunityID].ChildEntities.Count;
                    dr["Coefficient"] = measure.Coefficient;
                    dtClusters.Rows.Add(dr);
                }
            }
            return dtClusters;
        }

        public DataTable GetNetworkClusterEntitiesAsTable(string networkName)
        {
            DataTable dtClusterEntities = new DataTable();
            dtClusterEntities.Columns.Add("ClusterID", typeof(int));
            dtClusterEntities.Columns.Add("EntityName", typeof(string));

            Dictionary<int, NetworkCluster> clusters = NetworkCluster.Read(networkName);
            if (clusters != null && clusters.Count > 0)
            {
                foreach (NetworkCluster cluster in clusters.Values)
                {
                    if (cluster.ChildEntities != null && cluster.ChildEntities.Count > 0)
                    {
                        foreach (EntityBase entity in cluster.ChildEntities)
                        {
                            DataRow dr = dtClusterEntities.NewRow();
                            dr["ClusterID"] = cluster.ClusterID;
                            dr["EntityName"] = entity.Name;
                            dtClusterEntities.Rows.Add(dr);
                        }
                    }
                }
            }

            return dtClusterEntities;
        }
        #endregion

        #region subscribe events
        public void SubscribeViewStatsEventHandler(Network network)
        {
            this._Presenter.RegisterViewStatsEventHandler(network);
        }
        #endregion
    }
}
